package base

import (
	"gitee.com/wm1998/infra"
	log "github.com/sirupsen/logrus"
	"os"
	"os/signal"
	"reflect"
	"syscall"
)

// 钩子启动器
type HookStarter struct {
	infra.BaseStarter // 包含infra.BaseStarter接口，目的是可以选择性地实现该接口方法
}

var callbacks []func() // 回调函数切片

func Register(fn func()) {
	callbacks = append(callbacks, fn) // 将参数：函数类型变量添加到回调函数切片里
}

// 实现了启动器管理器接口的此方法
func (s *HookStarter) Init(ctx infra.StarterContext) {
	sigs := make(chan os.Signal)
	// 只需要注册2个信号量：syscall.SIGQUIT, syscall.SIGTERM
	signal.Notify(sigs, syscall.SIGQUIT, syscall.SIGTERM)
	go func() {
		for {
			c := <-sigs // 如果接收到来自于通道里的信号，则遍历存储回调函数的切片，依次执行每个回调函数
			log.Info("notify: ", c)
			for _, fn := range callbacks {
				fn() // 执行函数
			}
			break
			os.Exit(0)
		}
	}()
}

// 实现了启动器管理器接口的此方法
func (s *HookStarter) Start(ctx infra.StarterContext) {
	starters := infra.GetStarters()

	for _, s := range starters {
		typ := reflect.TypeOf(s)
		log.Infof("【Register Notify Stop】:%s.Stop()", typ.String())
		Register(func() {
			s.Stop(ctx)
		})
	}
}
